home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / dsp / 56200tar.z / 56200tar / 56200 / p7 < prev    next >
Text File  |  1992-04-28  |  28KB  |  546 lines

  1.  
  2.          /***********************************************\
  3.          |**                                           **|
  4.          |**   DSP56200 CHIP DRIVER -DUAL FIR FILTERS  **|
  5.          |**                        -INTERRUPT DRIVEN  **|
  6.          |**                                           **|
  7.          \***********************************************/
  8.  
  9.  
  10.  
  11. /************************************************************************\
  12. *                                                                        *
  13. *   This is an example of a program located in a host processor, used    *
  14. *   to setup and service a single DSP56200 as two real-time FIR filters. *
  15. *   In this example, the host processor is interrupted at the beginning  *
  16. *   of every new sample period, signified by the reception of a rising   *
  17. *   edge on the DSP56200's START pin.  The host processor's interrupt    *
  18. *   pin is tied to the START pin of the DSP56200 through an inverter.    *
  19. *                                                                        *
  20. *   This program, written in the language "C", is provided only as an    *
  21. *   example, and will be much faster if translated by the user into the  *
  22. *   assembly language of the host processor.                             *
  23. *                                                                        *
  24. *                                                                        *
  25. *   The example system is configured as shown below:                     *
  26. *                                                                        *
  27. *                                                                        *
  28. *                            ------------                                *
  29. *                            | DSP56200 |                                *
  30. *                            ------------                                *
  31. *                                  ^                                     *
  32. *                                  |                                     *
  33. *                                  v                                     *
  34. *               -------    ------------------    -------                 *
  35. *      x1(t) -->| A/D |--->| Host Processor |--->| D/A |--> out1(t)      *
  36. *               -------    |                |    -------                 *
  37. *                          | (contains code |                            *
  38. *               -------    |  found in this |    -------                 *
  39. *      x2(t) -->| A/D |--->|     file)      |--->| D/A |--> out2(t)      *
  40. *               -------    ------------------    -------                 *
  41. *                                                                        *
  42. *                                                                        *
  43. *                   Figure 1. Dual FIR Filtering System                  *
  44. *                                                                        *
  45. *                                                                        *
  46. *                                                                        *
  47. *   There is only one DSP56200 in this example (i.e., not multiple       *
  48. *   DSP56200s in cascade), and it is configured in the Dual FIR filter   *
  49. *   mode (Figure 2) by writing the DSP56200's Configuration register.    *
  50. *   Since only 16 bit  results  are sent to each D/A Converter, the      *
  51. *   outputs are rounded to 16 bits by the DSP56200.                      * 
  52. *                                                                        *
  53. *                                                                        *
  54. *                                                                        *
  55. *                                                                        *
  56. *                           --------------                               *
  57. *                           |  1st  FIR  |                               *
  58. *               x1(n) ----->|   Filter   |-----> out1(n)                 *
  59. *                           |  (7 taps)  |                               *
  60. *                           --------------                               *
  61. *                                                                        *
  62. *                           --------------                               *
  63. *                           |  2nd  FIR  |                               *
  64. *               x2(n) ----->|   Filter   |-----> out2(n)                 *
  65. *                           |  (7 taps)  |                               *
  66. *                           --------------                               *
  67. *                                                                        *
  68. *                                                                        *
  69. *                   Figure 2. DSP56200 Configuration                     *
  70. *                                                                        *
  71. *                                                                        *
  72. *      ************************************************************      *
  73. *      *                                                          *      *
  74. *      *   This program originally available on the Motorola DSP  *      *
  75. *      *   bulletin board.  It is provided under a DISCLAMER OF   *      *
  76. *      *   WARRANTY available from  Motorola DSP Operation,       *      *
  77. *      *     6501 Wm. Cannon Drive W., Austin, Tx., 78735.        *      *
  78. *      *                                                          *      *
  79. *      ************************************************************      *
  80. *                                                                        *
  81. *                                                                        *
  82. *                                                                        *
  83. *      ************************************************************      *
  84. *      * Note on the Representation of the Hex Numbers:           *      *
  85. *      *                                                          *      *
  86. *      *    In the programming language  "C",  hex numbers are    *      *
  87. *      *    represented by preceding the number with "0x". For    *      *
  88. *      *    example, e4 (hex) is represented in "C" as 0xe4.      *      *
  89. *      *                                                          *      *
  90. *      ************************************************************      *
  91. *                                                                        *
  92. \************************************************************************/
  93.  
  94.  
  95.  
  96.         /*** CONSTANTS ***/
  97.  
  98. #define   PASS_CONFIG   2       /* Pass for Configuring the DSP56200 */
  99. #define   PASS_RAMINIT  1       /* Pass for Initializing the RAMs    */
  100. #define   PASS_REALTIM  0       /* Pass for Realtime Filtering       */
  101.  
  102.  
  103.  
  104. #define   X1_HI     0x0         /* Addresses (hex) of DSP56200 regs, bank 0 */
  105. #define   X1_LO     0x1
  106. #define   D_HI      0x2                     /* unused -Adaptive mode only */
  107. #define   D_LO      0x3                     /* unused -Adaptive mode only */
  108. #define   K_HI      0x4                     /* unused -Adaptive mode only */
  109. #define   K_LO      0x5                     /* unused -Adaptive mode only */
  110. #define   X2_HI     0x6
  111. #define   X2_LO     0x7
  112. #define   DATA_HI   0x8                     /* unused */
  113. #define   DATA_LO   0x9                     /* unused */
  114. #define   COEFF_HI  0xa
  115. #define   COEFF_MD  0xb
  116. #define   COEFF_LO  0xc
  117. #define   RAM_ADR   0xd
  118. #define   CONFIG    0xf
  119.  
  120. #define   OUTPUT3   0x0              /* Most  significant byte of 1st result */
  121. #define   OUTPUT2   0x1              /* Least significant byte of 1st result */
  122. #define   OUTPUT1   0x2              /* Most  significant byte of 2nd result */
  123. #define   OUTPUT0   0x3              /* Least significant byte of 2nd result */
  124. #define   LTAP1_HI  0x4
  125. #define   LTAP1_LO  0x5
  126. #define   LTAP2_HI  0x6
  127. #define   LTAP2_LO  0x7
  128.  
  129. #define   LEAKAGE   0x0         /* Addresses (hex) of DSP56200 regs, bank 1 */
  130. #define   FTL       0x1
  131.  
  132.  
  133.  
  134.                                 /* Values (hex) written to the DSP56200 regs */
  135. #define   CNFIG_0   0x50              /* Config reg: Selects bank 0 */
  136. #define   CNFIG_1   0x51              /* Config reg: Selects bank 1 */
  137. #define   FTL_VAL   0x06              /* Two filters, each with 7 taps */
  138.  
  139.  
  140.         /*** GLOBAL VARS ***/
  141.  
  142. int  tap;                         /* Filter tap number, used to load coeffs */
  143. int  passnum;                     /* Determines action taken by the
  144.                                      interrupt service routine when
  145.                                      a START interrupt is received.  */
  146. static int coeff[14][3] = {
  147.    { 0x08, 0x00, 0x00 },            /* 1st coeff of 1st filter (3 bytes) */
  148.    { 0x10, 0x00, 0x00 },            /* 2nd coeff ...                     */
  149.    { 0x18, 0x00, 0x00 },            /* 3rd coeff ...                     */
  150.    { 0x20, 0x00, 0x00 },            /* 4th coeff ...                     */
  151.    { 0x18, 0x00, 0x00 },            /* 5th coeff ...                     */
  152.    { 0x10, 0x00, 0x00 },            /* 6th coeff ...                     */
  153.    { 0x08, 0x00, 0x00 },            /* 7th coeff ...                     */
  154.    { 0x08, 0x00, 0x00 },            /* 1st coeff of 2nd filter (3 bytes) */
  155.    { 0x10, 0x00, 0x00 },            /* 2nd coeff ...                     */
  156.    { 0x18, 0x00, 0x00 },            /* 3rd coeff ...                     */
  157.    { 0x20, 0x00, 0x00 },            /* 4th coeff ...                     */
  158.    { 0x18, 0x00, 0x00 },            /* 5th coeff ...                     */
  159.    { 0x10, 0x00, 0x00 },            /* 6th coeff ...                     */
  160.    { 0x08, 0x00, 0x00 }             /* 7th coeff ...                     */
  161. };                           /*  This two-dimensional array holds the 14    */
  162.                              /*  coefficients required for the two FIR      */
  163.                              /*  filters (each coeff is three bytes long).  */
  164.                              /*  Note that the coeffs of the 1st filter     */
  165.                              /*  don't have to be the same as those of the  */
  166.                              /*  2nd filter, but in this case they are the  */
  167.                              /*  same. The coefficients would typically be  */
  168.                              /*  stored in a ROM in an actual setup.        */
  169.  
  170.  
  171.  
  172.         /*** MAIN PROGRAM ***/
  173.  
  174. main()   {
  175.  
  176.         /********************************************************************\
  177.         *                                                                    *
  178.         *   This program is an example of the software used by a host        *
  179.         *   processor to service a DSP56200 configured in the Dual FIR       *
  180.         *   Filter mode.  Three functions are performed:                     *
  181.         *                                                                    *
  182.         *         1. Initialize User's System and Configure the DSP56200.    *
  183.         *         2. Initialize the Coeff and Data RAMs of the DSP56200.     *
  184.         *         3. Run the Dual FIR Filters in a real-time environment.    *
  185.         *                                                                    *
  186.         *   Things to watch for when setting up the filtering system:        *
  187.         *                                                                    *
  188.         *         - There must be NO GLITCHES on the DSP56200's START pin.   *
  189.         *         - If codecs are used for the A/D or D/A conversion, see    *
  190.         *              comments in the routines "send_da()"and "get_ad()".   *
  191.         *         - If offset binary A/Ds or D/As are used, see comments     *
  192.         *              in the subroutines "send_da()" and "get_ad()".        *
  193.         *         - Coefficients must be correctly selected so that there    *
  194.         *              is no overflow (see box below).                       *
  195.         *                                                                    *
  196.         *      ********************************************************      *
  197.         *      * Preventing Overflow:                                 *      *
  198.         *      *                                                      *      *
  199.         *      *    All FIR filters are subject to overflow, and it   *      *
  200.         *      *    is important that the filter coefficients are     *      *
  201.         *      *    carefully selected to prevent overflow.  For the  *      *
  202.         *      *    DSP56200, overflow occurs when the right side of  *      *
  203.         *      *    equation (1) has a magnitude greater than 1.0:    *      *
  204.         *      *                                                      *      *
  205.         *      *                    N-1                               *      *
  206.         *      *                    __                                *      *
  207.         *      *                    \                                 *      *
  208.         *      *          y(n)  =   /_   h(i) * x(n-i)        (1)     *      *
  209.         *      *                   i = 0                              *      *
  210.         *      *                                                      *      *
  211.         *      *    N represents the number of filter taps (N = 7     *      *
  212.         *      *    in this program), and h(i) represents the "ith"   *      *
  213.         *      *    filter coefficient.  Both h(i) and x(n-i) are     *      *
  214.         *      *    signed, fractional numbers  in the DSP56200's     *      *
  215.         *      *    data format.                                      *      *
  216.         *      *                                                      *      *
  217.         *      *    If there is a possibility of overflow with a set  *      *
  218.         *      *    of filter coefficients, then all coefficients     *      *
  219.         *      *    must be scaled by a constant.  The DSP56200's     *      *
  220.         *      *    24 bit coefficients allow plenty of room for      *      *
  221.         *      *    scaling. If 12 bit input data samples are used in *      *
  222.         *      *    a system, the potential for overflow is greatly   *      *
  223.         *      *    reduced if the samples are sign-extended by four  *      *
  224.         *      *    bits before sending them to the DSP56200.         *      *
  225.         *      *                                                      *      *
  226.         *      ********************************************************      *
  227.         *                                                                    *
  228.         *                                                                    *
  229.         *   Note: The program assumes that the variable type "int" is at     *
  230.         *         least 16 bits wide.                                        *
  231.         *                                                                    *
  232.         \********************************************************************/
  233.  
  234.  
  235.  
  236.         /* Program Setup */
  237.  
  238.            /* The host must disable the START Interrupt */
  239.  
  240.            /* Then, global vars are set up for the routine "irealtime()" */
  241.               passnum = PASS_CONFIG;
  242.               tap = 0;
  243.  
  244.  
  245.  
  246.         /* Initialize System */
  247.  
  248.            /*   Here the user first initializes any other components of     */
  249.            /*   the filtering system which require initialization.  The     */
  250.            /*   DSP56200 is then initialized using the program code below.  */
  251.  
  252.  
  253.  
  254.         /* The host must now enable the START Interrupt */
  255.  
  256.  
  257.  
  258.         /* Run the Filters in Real-time */
  259.  
  260.            /*  At this point the program can either start executing some     */
  261.            /*  other task or it can idle.  Upon reception of a START signal  */
  262.            /*  (i.e. when interrupted), the host calls the interrupt service */
  263.            /*  routine "irealtime()".  Upon completion of "irealtime()",     */
  264.            /*  the host either continues its other processing or idles.      */
  265. }
  266.  
  267.  
  268.  
  269.         /*** SUBROUTINES ***/
  270.  
  271.  
  272.  
  273.         /* IREALTIME */
  274.  
  275. irealtime()
  276. {
  277.         /****************************************************************\
  278.         *                                                                *
  279.         *   This interrupt service routine will perform one of the       *
  280.         *   following three tasks when executed:                         *
  281.         *                                                                *
  282.         *         Task 1. Configure the DSP56200.                        *
  283.         *                                                                *
  284.         *         Task 2. Clear one location in the Data RAM and         *
  285.         *                 load one location in the Coefficient RAM.      *
  286.         *                                                                *
  287.         *         Task 3. Send two new data samples to the DSP56200      *
  288.         *                 and read out two FIR results from the chip.    *
  289.         *                                                                *
  290.         *   When the user's system comes out of reset, the DSP56200 is   *  
  291.         *   first configured (Task 1).  Then, the host processor will    *
  292.         *   execute Task 2 when interrupted so that the DSP56200 RAMs    *
  293.         *   get initialized.  Upon receiving each new interrupt, Task 2  *
  294.         *   is executed until the RAM initialization is completed.  The  *
  295.         *   host processor then executes Task 3 with each new interrupt  *
  296.         *   it receives.                                                 *
  297.         *                                                                *
  298.         *   This routine is used only in interrupt driven systems.       *
  299.         *   Since this is an interrupt service routine, it may be        *
  300.         *   necessary to save the status of the host processor upon      *
  301.         *   entering this routine, and to restore the processor's        *
  302.         *   status upon exiting this routine.  It may also be important  *
  303.         *   to disable any interrupts of lower priority when entering    *
  304.         *   this routine, and to reenable these interrupts upon exiting. *
  305.         *                                                                *
  306.         *   Note: The routine assumes that the variable type "int" is    *
  307.         *         at least 16 bits wide.                                 *
  308.         *                                                                *
  309.         *   Also: It is important that execution of this routine         *
  310.         *         completes before the next START interrupt arrives,     *
  311.         *         i.e., it must complete in one sample period.   If      *
  312.         *         Task 1 will not complete in one sample period, it      *
  313.         *         can be broken into two shorter tasks, requiring        *
  314.         *         two sample periods.                                    *
  315.         *                                                                *
  316.         \****************************************************************/
  317.  
  318.  
  319.  
  320.         /* Subroutine Declarations */
  321.            int x1, x2, out;                       /* see Figure 2 */
  322.  
  323.  
  324.  
  325.         /* Select Correct Task to Execute */
  326.  
  327.         /* Task 1 */
  328.  
  329.            if (passnum == PASS_CONFIG)   {
  330.  
  331.               /* Reset and Configure the DSP56200 */
  332.  
  333.                  wrbyte(CNFIG_1, CONFIG);  /* Configuration:                */
  334.                                            /*    - Dual FIR Filters         */
  335.                                            /*    - Not Cascaded             */
  336.                                            /*    - 16 Bit Rounding          */
  337.                                            /*    - DC Tap Disabled          */
  338.                                            /*    - Register Bank 1 Selected */
  339.                  wrbyte(FTL_VAL, FTL);     /* Writing this reg also resets   */
  340.                                            /*    the chip at the beginning   */
  341.                                            /*    of the next sample period,  */
  342.                                            /*    which destroys any previous */
  343.                                            /*    contents of the Data RAM.   */
  344.  
  345.                  wrbyte(CNFIG_0, CONFIG);       /* Switch to register bank 0 */
  346.  
  347.  
  348.  
  349.               /* Setup the DSP56200 registers for RAM initialization */
  350.  
  351.                  wrbyte(0, X1_HI);   /* clears Data RAM when loading coeffs */
  352.                  wrbyte(0, X1_LO);
  353.  
  354.                  wrbyte(0, X2_HI);
  355.                  wrbyte(0, X2_LO);
  356.  
  357.                  wrbyte(coeff[0][0], COEFF_HI);   /* 1st coeff of 1st FIR */
  358.                  wrbyte(coeff[0][1], COEFF_MD);
  359.                  wrbyte(coeff[0][2], COEFF_LO);
  360.  
  361.                  wrbyte(0, RAM_ADR);      /* autoincrements w/ each START */
  362.  
  363.                  passnum = passnum-1;            /* Goes to PASS_RAMINIT on
  364.                                                     next START interrupt */
  365.               /* Exit Routine */
  366.                  return;
  367.            }
  368.  
  369.         /* Task 2 */
  370.  
  371.            if (passnum == PASS_RAMINIT)   {
  372.  
  373.               /* Load One Coeff into the DSP56200's Coefficient RAM */
  374.  
  375.                  tap = tap + 1;
  376.  
  377.                  wrbyte(coeff[tap][0], COEFF_HI);
  378.                  wrbyte(coeff[tap][1], COEFF_MD);
  379.                  wrbyte(coeff[tap][2], COEFF_LO);
  380.                                      /*  Note that the Data RAM is cleared   */
  381.                                      /*  since the DSP56200's X1 and X2 regs */
  382.                                      /*  are set to "0", resulting in "0"s   */
  383.                                      /*  being "shifted" into the filter's   */
  384.                                      /*  Data RAM (delay line) every sample  */
  385.                                      /*  period.                             */
  386.  
  387.                  if (tap == (1 + 2*FTL_VAL))
  388.                     passnum = passnum-1;            /* Goes to PASS_REALTIM on
  389.                                                        next START interrupt */
  390.  
  391.               /* Exit Routine */
  392.                  return;
  393.            }
  394.  
  395.         /* Task 3 */
  396.  
  397.            if (passnum == PASS_REALTIM)   {
  398.  
  399.               /* Read New Samples from the A/Ds and Write to the DSP56200 */
  400.  
  401.                  x1 = get_ad(1);
  402.                  x2 = get_ad(2);
  403.  
  404.                  wrbyte((x1>>8) & 0x0ff, X1_HI);      /* writes upper byte */
  405.                  wrbyte( x1     & 0x0ff, X1_LO);      /* writes lower byte */
  406.                  wrbyte((x2>>8) & 0x0ff, X2_HI);      /* writes upper byte */
  407.                  wrbyte( x2     & 0x0ff, X2_LO);      /* writes lower byte */
  408.  
  409.               /* Read the Results from the 56200 and Write to the D/As */
  410.  
  411.                  out = rdbyte(OUTPUT3);
  412.                  out = out << 8;                      /* move to upper byte */
  413.                  out = out + (0x0ff & rdbyte(OUTPUT2));
  414.                  send_da(out,1);
  415.  
  416.                  out = rdbyte(OUTPUT1);
  417.                  out = out << 8;                      /* move to upper byte */
  418.                  out = out + (0x0ff & rdbyte(OUTPUT0));
  419.                  send_da(out,2);
  420.  
  421.               /* Exit Routine */
  422.                  return;
  423.            }
  424. }
  425.  
  426.  
  427.  
  428.         /* WRBYTE */
  429.  
  430. wrbyte(val,adr)
  431. int val, adr;
  432. {
  433.         /**************************************************************\
  434.         *                                                              *
  435.         *   This subroutine writes one byte to the DSP56200 register   *
  436.         *   specified by "adr".                                        *
  437.         *   Note that the correct register bank has already been       *
  438.         *   selected (defined by the LSB of the Configuration reg).    *
  439.         *                                                              *
  440.         *   This subroutine could be defined as a macro for faster     *
  441.         *   execution.                                                 *
  442.         *                                                              *
  443.         *   Inputs:                                                    *
  444.         *      val  = bytewide value to be written to the DSP56200     *
  445.         *      adr  = address of the DSP56200 register to be written   *
  446.         *                                                              *
  447.         \**************************************************************/
  448.  
  449.         /* Actual program code depends on the user's system. */
  450. }
  451.  
  452.  
  453.  
  454.         /* RDBYTE */
  455.  
  456. rdbyte(adr)
  457. int adr;
  458. {
  459.         /**************************************************************\
  460.         *                                                              *
  461.         *  This subroutine reads one byte from the DSP56200 register   *
  462.         *  specified by "adr".                                         *
  463.         *  Note that the correct register bank has already been        *
  464.         *  selected (defined by the LSB of the Configuration reg).     *
  465.         *                                                              *
  466.         *  This subroutine could be defined as a macro for faster      *
  467.         *  execution.                                                  *
  468.         *                                                              *
  469.         *   Inputs:                                                    *
  470.         *      adr  = address of the DSP56200 register to be read      *
  471.         *                                                              *
  472.         *   Outputs:                                                   *
  473.         *      The routine returns the byte read from the DSP56200     *
  474.         *                                                              *
  475.         \**************************************************************/
  476.  
  477.         int valread;
  478.  
  479.         /* Actual program code depends on the user's system. */
  480.  
  481.         return(valread);
  482. }
  483.  
  484.  
  485.  
  486.         /* GET_AD */
  487.  
  488. get_ad(devnum)
  489. int devnum;
  490. {
  491.         /******************************************************************\
  492.         *                                                                  *
  493.         *   This subroutine returns a 16 bit value read from one of the    *
  494.         *   two A/D converters in the filtering system.                    *
  495.         *                                                                  *
  496.         *   Inputs:                                                        *
  497.         *      devnum = A/D Converter number:  1=1st FIR, 2=2nd FIR.       *
  498.         *                                                                  *
  499.         *   Outputs:                                                       *
  500.         *      The routine returns the value read from the selected A/D.   *
  501.         *                                                                  *
  502.         \******************************************************************/
  503.  
  504.         int ad_val;
  505.  
  506.         /* Actual program code depends on the user's system. */
  507.  
  508.         /*  If a codec is used for A/D conversion, the 8 bit companded  */
  509.         /*  sample must be converted into a 12 bit linear quantity and  */
  510.         /*  then sign extended to 16 bits.                              */
  511.  
  512.         /*  If the converter uses an offset binary format, it may be  */
  513.         /*  necessary to invert the sign bit (and any sign extension  */
  514.         /*  bits) to obtain a 2's complement number.                  */
  515.  
  516.         return(ad_val);
  517. }
  518.  
  519.  
  520.  
  521.         /* SEND_DA */
  522.  
  523. send_da(val,devnum)
  524. int val, devnum;
  525. {
  526.         /**************************************************************\
  527.         *                                                              *
  528.         *   This subroutine sends a value to a D/A converter where it  *
  529.         *   gets converted to an analog signal.                        *
  530.         *                                                              *
  531.         *   Inputs:                                                    *
  532.         *      val = value to be sent to the selected D/A converter    *
  533.         *      devnum = D/A Converter number:  1=1st FIR, 2=2nd FIR.   *
  534.         *                                                              *
  535.         \**************************************************************/
  536.  
  537.         /* Actual program code depends on the user's system. */
  538.  
  539.         /*  If a codec is used for D/A conversion, the 16 bit linear   */
  540.         /*  sample must be converted into a 8 bit companded quantity.  */
  541.  
  542.         /*  If the converter uses an offset binary format, it may be  */
  543.         /*  necessary to invert the sign bit (and any sign extension  */
  544.         /*  bits) to obtain a number in offset binary format.         */
  545. }
  546.